#ifndef TASK_H
#define TASK_H

#include "comm/types.h"
#include "cpu/cpu.h"
#include "tools/list.h"
#include "fs/file.h"

#define TASK_NAME_SIZE              32
#define TASK_TIME_SLICE_DEFAULT     10          //每100ms进行一次任务切换
#define TASK_OFILE_NR               128

#define TASK_FLAGS_SYSTEM           (1 << 0)
#define TASK_FLAGS_USER             (0 << 0)

typedef struct _task_t {
    enum {
        TASK_CREATED,
        TASK_RUNNING,
        TASK_SLEEP,
        TASK_READY,
        TASK_WAITTING,
        TASK_ZOOMBIE,
    } state;

    int pid;
    int status;                     // 程序退出状态信息
    struct _task_t *parent;
    char name[TASK_NAME_SIZE];

    file_t *file_table[TASK_OFILE_NR];

    uint32_t heap_start;
    uint32_t heap_end;

    uint32_t time_ticks;
    uint32_t slice_ticks;
    uint32_t sleep_ticks;

    list_node_t run_node;           // 可以被放入进程运行队列和睡眠等待队列
    list_node_t wait_node;          // 可以被放入进程等待信号量队列
    list_node_t all_node;           // 被放入进程队列（维护了系统中的所有进程）

    tss_t tss;
    uint32_t tss_sel;
} task_t;

typedef struct _task_manager_t {
    task_t *curr_task;          // 当前正在执行的任务
    list_t ready_list;          // 就绪队列
    list_t task_list;           // 任务队列
    list_t sleep_list;          // 睡眠队列

    task_t first_task;          // 第一个任务
    task_t idle_task;           // 空闲任务

    int app_code_sel;
    int app_data_sel;
} task_manager_t;

typedef struct _task_args_t {
    uint32_t ret_addr;
    uint32_t argc;
    char **argv;
} task_args_t;

// 参数flag表示进程初始化时的标志控制位，从而控制task_init对不同类型的进程进行不同的初始化
int task_init(task_t *task, const char *name, int flag, uint32_t entry, uint32_t esp);
void task_switch_from_to(task_t *from, task_t *to);
void task_time_tick(void);

task_t * task_current();
task_t * task_first_task(void);
void task_first_init(void);
void task_manager_init(void);
void task_set_ready(task_t *task);
void task_set_block(task_t *task);
void task_dispatch(void);        // 处理器分配函数
void task_set_sleep(task_t *task, uint32_t ticks);
void task_set_wakeup(task_t *task);
file_t *task_file(int fd);
int task_alloc_fd(file_t *file);
void task_remove_fd(int fd);

int sys_yield(void);
void sys_sleep(uint32_t ms);
int sys_getpid(void);
int sys_fork(void);
int sys_execve(char *name, char **argv, char **env);
void sys_exit(int status);
int sys_wait(int *status);

#endif